package net.sk.china.platform.config;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.useragent.UserAgent;
import cn.hutool.http.useragent.UserAgentUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import io.swagger.annotations.ApiOperation;
import net.sk.china.platform.constants.Constants;
import net.sk.china.platform.model.SensitiveLog;
import net.sk.china.platform.response.system.LoginSystemResponse;
import net.sk.china.platform.service.SensitiveLogService;
import net.sk.china.platform.token.TokenComponent;
import net.sk.china.common.annotation.Log;
import net.sk.china.common.utils.DateUtil;
import net.sk.china.common.utils.TalkUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.*;

/**
 * AOP 切面类
 * +----------------------------------------------------------------------
 * | Talk To [ 聊来改善地区金融服务环境，助力企业发展 ]
 * +----------------------------------------------------------------------
 * | Copyright (c) 2018-2024 聊来All rights reserved.
 * +----------------------------------------------------------------------
 * | Licensed ( <a href="http://www.apache.org/licenses/LICENSE-2.0">apache</a> )
 * +----------------------------------------------------------------------
 * | @Author: 聊来 <18970881148@qq.com>
 * +----------------------------------------------------------------------
 * | DateTime: 2024/6/3 18:21
 * +----------------------------------------------------------------------
 */

@Component
@Aspect
public class AspectAopConfig {

    @Resource
    private TokenComponent tokenComponent;

    private final SensitiveLogService sensitiveLogService;

    public AspectAopConfig(SensitiveLogService sensitiveLogService) {
        this.sensitiveLogService = sensitiveLogService;
    }

    @Pointcut("@annotation(net.sk.china.common.annotation.Log)")
    private void pointcut() {

    }

    /**
     * 环绕操作
     * @param point 切入点
     * @return {@code Object}
     */
    @Around("pointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 获取被增强类和方法的信息
        Signature signature = point.getSignature();

        // 方法名称
        String method = signature.getDeclaringTypeName() + "." + signature.getName() + "()";

        // 获取被增强的方法对象
        MethodSignature methodSignature = (MethodSignature) signature;
        Method methodSignatureMethod = methodSignature.getMethod();

        // 接口描述、请求类型
        Log log = methodSignatureMethod.getAnnotation(Log.class);
        String description = Optional.ofNullable(log.description()).orElse("");

        ApiOperation operation = methodSignatureMethod.getAnnotation(ApiOperation.class);
        String methType = Optional.ofNullable(operation.value()).orElse("");
        if (StrUtil.isBlank(description)) {
            description = Optional.ofNullable(operation.value()).orElse("");
        }

        // 请求参数
        Object[] args = point.getArgs();
        List<String> list = new ArrayList<>();
        try{
            for (Object param : args) {
                list.add(JSONObject.toJSONString(param));
            }
        } catch (Exception e){ }

        // 获取Request对象
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = Objects.requireNonNull(servletRequestAttributes).getRequest();

        // 访问的url
        String url = request.getRequestURI();

        // 请求方式
        String requestMethod = request.getMethod();

        // 获取UA信息
        String header = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgentUtil.parse(header);

        // 获取管理员身份信息
        LoginSystemResponse loginUser = tokenComponent.getLoginUser(request);

        // 返回的参数
        String res = JSONObject.toJSONString(point.proceed(), SerializerFeature.WriteMapNullValue);
        JSONObject json = JSONObject.parseObject(res);
        int status; String result = ""; String errorMsg = "";
        if (json.getInteger("code").equals(Constants.NUM_TWO_HUNDRED)) {
            status = Constants.NUM_ZERO;
            result = res;
        } else {
            status = Constants.NUM_ONE;
            errorMsg = res;
        }

        SensitiveLog sensitiveLog = new SensitiveLog();
        sensitiveLog.setAdminId(loginUser.getUser().getId()).setAdminAccount(loginUser.getUser().getAccount()).setUrl(url).setIp(TalkUtil.getClientIp(request)).setMethod(method).setMethodType(methType).setRequestMethod(requestMethod)
                .setRequestParam(list.toString()).setDescription(description).setBrowser(userAgent.getBrowser().toString()).setPlatform(userAgent.getPlatform().toString())
                .setStatus(status).setResult(result).setErrorMsg(errorMsg).setCreateTime(DateUtil.getNowTime());
        sensitiveLogService.save(sensitiveLog);

        return point.proceed();
    }

}
